package com.deimos.sps;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.vast.ows.OWSException;
import org.vast.ows.sps.GetFeasibilityResponse;
import org.vast.ows.sps.GetStatusRequest;
import org.vast.ows.sps.GetStatusResponse;
import org.vast.ows.sps.ReservationReport;
import org.vast.ows.sps.StatusReport;
import org.vast.ows.sps.TaskingResponse;
import org.vast.ows.sps.StatusReport.TaskStatus;
import org.vast.util.DateTime;
import org.w3c.dom.Element;
import com.deimos.UtilsDeimos;
import com.deimos.dataBase.Event;
import com.deimos.dataBase.Segment;
import com.deimos.dataBase.Sensor;
import com.deimos.dataBase.Task;
import com.deimos.dataBase.TaskController;
import com.deimos.sps.GetFeasibility.Operation;
import com.spotimage.eosps.EOReportHelper;
import com.spotimage.eosps.EOConstants.AcqStatus;
import com.spotimage.eosps.EOConstants.ReportType;

public class GetStatus {
    GetStatusRequest request = null;
    GetStatusResponse response = null;
    Task task = null;

    public GetStatus(GetStatusRequest request) {
	this.request = request;
    }

    @SuppressWarnings("unchecked")
    public GetStatusResponse buildResponse() throws OWSException {
	String id = request.getTaskID();

	TaskController taskController = new TaskController();
	ReservationReport rs = null;
	// StatusReport sr = null;
	List<StatusReport> reports = null;
	List<Event> events = null;

	taskController.validateStatus(id);
	taskController.validateSegments(id);

	response = new GetStatusResponse();
	// reports = response.getReports();
	reports = new ArrayList<StatusReport>();

	// request.setSince(null);

	task = taskController.getTask(id);
	events = taskController.getEventsSince(id, null);
	/*if (request.getSince() == null) {
	    events = taskController.getEventsSince(id, request.getSince());
	} else {
	    try {
		events = taskController.getEventsSince(id, GetFeasibility.sdf_hma.parse(request.getSince().formatIso(0)));
	    } catch (ParseException e) {
		e.printStackTrace();
	    }
	}*/

	for (Event event : events) {
	    rs = new ReservationReport();
	    rs.setRequestStatus(event.getRequestStatus());
	    rs.setTaskStatus(event.getTaskStatus());
	    rs.setTaskID(event.getTask().getTaskId());
	    rs.setDescription(event.getDescription());

	    try {
		Iterator it = UtilsDeimos.readParams(event.getResponseParameters()).getReport().getExtensions().entrySet().iterator();
		while (it.hasNext()) {
		    Map.Entry e = (Map.Entry) it.next();
		    rs.addExtension((Element) e.getValue());
		}
	    } catch (Exception e) {
		e.printStackTrace();
	    }

	    if (event.getTask().getDelay() != null)
		rs.setEstimatedDelay(event.getTask().getDelay().intValue());
	    if (event.getEstimatedToC() != null)
		rs.setEstimatedToC(new DateTime(event.getEstimatedToC().getTime()));
	    if (event.getUpdateDate() != null)
		rs.setLastUpdate(new DateTime(event.getUpdateDate().getTime()));
	    rs.setTitle(event.getTask().getTitle());
	    rs.setSensorID(event.getTask().getSensorId());

	    if (request.getSince() == null)
		onlyAcquired(rs, event.getOperation(), new Sensor(event.getTask().getSensorId()));
	    if (request.getSince() != null)
		try {
		    onlySince(rs, GetFeasibility.sdf_hma.parse(request.getSince().formatIso(0)), event.getOperation(), new Sensor(event.getTask().getSensorId()));
		} catch (ParseException e) {
		}

	    if (event.getTaskStatus() == TaskStatus.Reserved) {
		if (event.getExpirationDate() != null)
		    rs.setReservationExpiration(new DateTime(event.getExpirationDate().getTime()));
		reports.add(rs);
	    } else {
		reports.add(UtilsDeimos.getStatusReport(rs));
	    }

	    response.setReportList(reports);
	}

	if (events == null || events.size() == 0) {
	    if (task != null)
		throw new OWSException(OWSException.invalid_param_code, "procedure", request.getTaskID(), "Events not found into the database");
	    else if (task == null)
		throw new OWSException(OWSException.invalid_param_code, "task", request.getTaskID(), "task not found into the database");
	}

	response.setVersion("2.0.0");
	response.setService("SPS");
	// setSegmentsStatus();
	return response;
    }

    @SuppressWarnings("unchecked")
    public void onlyAcquired(ReservationReport report, Operation operation, Sensor sensor) {
	try {
	    TaskingResponse response = new GetFeasibilityResponse();
	    EOReportHelper eohelper = new EOReportHelper(report);
	    EOReportHelper neweohelper;
	    report.getExtensions().clear();
	    response.setReport(new ReservationReport());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
		neweohelper = new EOReportHelper(response, ReportType.FEASIBILITY);
	    else 
		neweohelper = new EOReportHelper(response, ReportType.PROG_STATUS);
	    if (eohelper.getReportType() == null) return;
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    neweohelper.setEstimatedCost(eohelper.getEstimatedCost());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    for (int j = 0; j < eohelper.getInformationUsed().size(); j++)
		neweohelper.addInformationUsed(eohelper.getInformationUsed().get(j));
	    // neweohelper.setExpirationDelay(eohelper.ge());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    neweohelper.setOverallSuccessRate(eohelper.getOverallSuccessRate());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    neweohelper.setExpirationDate(eohelper.getExpirationDate());
	    for (int i = 0; i < eohelper.getNumSegments(); i++) {
		eohelper.loadSegment(i);
		if (eohelper.getObjectStatus() == AcqStatus.ACQUIRED || eohelper.getObjectStatus() == AcqStatus.VALIDATED) {
		    neweohelper.addSegment();
		    neweohelper.loadSegment(neweohelper.getNumSegments() - 1);
		    neweohelper.setID(eohelper.getID());
		    neweohelper.setObjectStatus(eohelper.getObjectStatus());
		    neweohelper.setPlatformID(eohelper.getPlatformID());
		    neweohelper.setPlatformName(eohelper.getPlatformName());
		    neweohelper.setInstrumentName(eohelper.getInstrumentName());
		    neweohelper.setInstrumentMode(eohelper.getInstrumentMode());
		    if (Operation.STUDIED == operation || !sensor.isSyn())
		    neweohelper.setExpirationDate(eohelper.getExpirationDate());
		    neweohelper.setAcquisitionStart(eohelper.getAcquisitionStart());
		    neweohelper.setAcquisitionStop(eohelper.getAcquisitionStop());
		    neweohelper.setFootprint(eohelper.getFootprint());
		    neweohelper.setNumGridCells(eohelper.getNumGridCells());
		}
	    }
	    neweohelper.writeReportInfo();
	    response.getReport().touch();
	    report.getExtensions().clear();

	    report.getExtensions().putAll(response.getReport().getExtensions());
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    @SuppressWarnings("unchecked")
    public void onlySince(StatusReport report, Date since, Operation operation, Sensor sensor) {
	try {
	    TaskController taskController = new TaskController();
	    TaskingResponse response = new GetFeasibilityResponse();
	    EOReportHelper eohelper = new EOReportHelper(report);
	    report.getExtensions().clear();
	    response.setReport(new ReservationReport());
	    EOReportHelper neweohelper;
	    if (Operation.STUDIED == operation || !sensor.isSyn())
		neweohelper = new EOReportHelper(response, ReportType.FEASIBILITY);
	    else 
		neweohelper = new EOReportHelper(response, ReportType.PROG_STATUS);
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    neweohelper.setEstimatedCost(eohelper.getEstimatedCost());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    for (int j = 0; j < eohelper.getInformationUsed().size(); j++)
		neweohelper.addInformationUsed(eohelper.getInformationUsed().get(j));
	    // neweohelper.setExpirationDelay(eohelper.ge());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    neweohelper.setOverallSuccessRate(eohelper.getOverallSuccessRate());
	    if (Operation.STUDIED == operation || !sensor.isSyn())
	    neweohelper.setExpirationDate(eohelper.getExpirationDate());
	    for (int i = 0; i < eohelper.getNumSegments(); i++) {
		eohelper.loadSegment(i);
		Segment segment = taskController.getSegment(report.getTaskID(), eohelper.getID());
		if ((segment != null && segment.getUpdateDate() != null && segment.getUpdateDate().after(since)) || Operation.STUDIED == operation) {
		    neweohelper.addSegment();
		    neweohelper.loadSegment(neweohelper.getNumSegments() - 1);
		    neweohelper.setID(eohelper.getID());
		    neweohelper.setObjectStatus(eohelper.getObjectStatus());
		    neweohelper.setPlatformID(eohelper.getPlatformID());
		    neweohelper.setPlatformName(eohelper.getPlatformName());
		    neweohelper.setInstrumentName(eohelper.getInstrumentName());
		    neweohelper.setInstrumentMode(eohelper.getInstrumentMode());
		    if (Operation.STUDIED == operation || !sensor.isSyn())
		    neweohelper.setExpirationDate(eohelper.getExpirationDate());
		    neweohelper.setAcquisitionStart(eohelper.getAcquisitionStart());
		    neweohelper.setAcquisitionStop(eohelper.getAcquisitionStop());
		    neweohelper.setFootprint(eohelper.getFootprint());
		    neweohelper.setNumGridCells(eohelper.getNumGridCells());
		}
	    }
	    neweohelper.writeReportInfo();
	    response.getReport().touch();
	    report.getExtensions().clear();

	    report.getExtensions().putAll(response.getReport().getExtensions());
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }
}
